Skip to content

Restore the absence entry that carries its own reason and the guard over it (#155) - #157

Merged
iderex merged 1 commit into
mainfrom
contexts/the-permanent-absence-guard-left-the-default-branch
Aug 21, 2026
Merged

Restore the absence entry that carries its own reason and the guard over it (#155)#157
iderex merged 1 commit into
mainfrom
contexts/the-permanent-absence-guard-left-the-default-branch

Conversation

@iderex

@iderex iderex commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Refs #155

What this changes

internal/contexts/contexts.go and internal/contexts/contexts_test.go, back to
the bytes the default branch held at 90656ba77a7c930d04d2205b2dd99df787853a92.

Two things come back together. The zizmor entry in Absences carries its own
reason again, saying that the name is created by the code-scanning upload in
zizmor.yml rather than by the job and that the job reports under a different
string, with Until empty because that absence does not end when the required
set is assembled. And TestAPermanentAbsenceDoesNotRestOnAReasonThatEnds comes
back with it, which is the guard that refuses an entry written as permanent
whose reason is the one that stops being true.

Both are the bytes that were there rather than a retyping of them:

git rev-parse 90656ba:internal/contexts/contexts.go
9608b17ec822791856dd866411c1c1835079e1d9
git hash-object internal/contexts/contexts.go
9608b17ec822791856dd866411c1c1835079e1d9
git rev-parse 90656ba:internal/contexts/contexts_test.go
9bdd8745837bdbaf21d41915d537fbafaab61cff
git hash-object internal/contexts/contexts_test.go
9bdd8745837bdbaf21d41915d537fbafaab61cff

The means is Go in the package that already holds the entry and the suite that
already judges it, so nothing here adds a language, a runtime, a dependency or a
place to look, and the guard is testable by the suite that exists.

How the absence arrived

d3edfc95b8526033c79cb26afe48282c2c090e32 took its tree from an older state of
the default branch and landed on top of a newer one, under a message describing a
change to how one workflow pin is commented. Both files were among the seven
paths it replaced, and that commit is the only one to have touched this package
since:

git log --format='%H %s' 90656ba..origin/main -- internal/contexts/
d3edfc95b8526033c79cb26afe48282c2c090e32 Name the version the pinned commit actually is (#151)

Because it is the only one, taking the whole blob drops nothing that arrived
afterwards.

What failure it prevents

An absence declared permanent while resting on a reason that ends. Until empty
says the entry outlives the day the required set is assembled, and the shared
reason says the name is outside the set because the set has no members, which is
exactly the condition that day ends. An entry carrying both reads as settled to
whoever assembles the set.

I proved the guard bites by making the near-miss it names, which is one field:
emptying Until on an entry whose reason is still the shared one. With the guard
restored, that reddens one test in the tree and nothing else:

go test ./... -count=1
--- FAIL: TestAPermanentAbsenceDoesNotRestOnAReasonThatEnds (0.00s)
    contexts_test.go:297: the absence "DCO sign-off" is written as permanent and its reason is that the required set is empty, which is the condition that ends when the set is assembled, so the entry says the absence outlives the only thing it rests on
FAIL	github.com/Flowfin/lab/internal/contexts	0.660s

The same near-miss against what the default branch holds today, with the guard
absent, runs green in all eleven packages, so nothing there separated an entry
resting on a debt from one that does not. That is what the absence cost, measured
rather than supposed.

What was run

At 68079e9402db63c569b8f549c339e98510d08ba6, on Windows, with no graphical
session and as an ordinary user:

go build ./cmd/... ./internal/...
go vet ./cmd/... ./internal/...
gofmt -l cmd internal
go test -count=1 ./cmd/... ./internal/...
ok  	github.com/Flowfin/lab/cmd/contexts	0.423s
ok  	github.com/Flowfin/lab/cmd/lab	3.734s
ok  	github.com/Flowfin/lab/cmd/notices	13.501s
ok  	github.com/Flowfin/lab/cmd/pullrequest	0.436s
ok  	github.com/Flowfin/lab/internal/check	0.886s
ok  	github.com/Flowfin/lab/internal/contexts	0.429s
ok  	github.com/Flowfin/lab/internal/hardware	0.438s
ok  	github.com/Flowfin/lab/internal/invariants	0.914s
ok  	github.com/Flowfin/lab/internal/notices	0.625s
ok  	github.com/Flowfin/lab/internal/prose	0.643s
ok  	github.com/Flowfin/lab/internal/pullrequest	0.901s

go build, go vet and gofmt -l each printed nothing, which is the passing
result for all three.

go run ./cmd/lab check .
examined .
1 experiment directory walked, 1 record read
18 decision records read
the time this run read is 2026-08-21T13:53:59Z
0 refused

No test here was skipped for needing elevation, and none was run with any.

What this does not do

It does not finish #155. Five of the six path groups that commit removed are
still missing: LICENSE with the ## License section of README.md, two
sections of docs/quality-parity.md, sixteen comment lines in
.github/workflows/codeql.yml, the pin comment in .github/workflows/zizmor.yml
and fifteen lines of docs/operator-guide.md.

It does not touch the second question #155 raises, which is whether anything here
should refuse a merge that removes a tracked path without saying so in its body.
Restoring a file does not answer that and this change does not pretend to.

It does not move #26. The zizmor entry's own reason and the guard over it are
what landed for that issue and were removed; the required set on the default
branch is untouched here.

No second person has read this change. The evidence above stands in place of one,
and that is a disclosure rather than an assurance.

…ver it (#155)

This does not finish #155. Five more of the paths that commit removed are still
missing, and the question of whether a merge removing a tracked path should be
refused is not touched here.

What was wrong. `d3edfc95b8526033c79cb26afe48282c2c090e32` took its tree from an
older state of the default branch and landed on top of a newer one, under a
message describing a change to how one workflow pin is commented. Among the
seven paths it replaced were both files in `internal/contexts`. The `zizmor`
entry went back to giving the shared reason and naming #26 as what ends it, and
`TestAPermanentAbsenceDoesNotRestOnAReasonThatEnds` went with it:

    git log --diff-filter=M --format='%H %s' origin/main -- internal/contexts/contexts_test.go
    d3edfc9 Name the version the pinned commit actually is (#151)

Both blobs are the bytes that were there rather than a retyping of them:

    git rev-parse 90656ba:internal/contexts/contexts.go
    9608b17
    git hash-object internal/contexts/contexts.go
    9608b17
    git rev-parse 90656ba:internal/contexts/contexts_test.go
    9bdd874
    git hash-object internal/contexts/contexts_test.go
    9bdd874

What failure this prevents is an absence written as permanent whose reason is
the one that stops being true the day the required set is assembled. The guard
reads `Until` and `Why` together and refuses an entry carrying both, and the
near-miss it is written for is one field: emptying `Until` on an entry whose
reason is still the shared one.

I proved it bites by making that near-miss. With `Until` emptied on the
`DCO sign-off` entry and the guard back, one test reddens and nothing else does:

    --- FAIL: TestAPermanentAbsenceDoesNotRestOnAReasonThatEnds (0.00s)
        contexts_test.go:297: the absence "DCO sign-off" is written as permanent and its reason is that the required set is empty, which is the condition that ends when the set is assembled, so the entry says the absence outlives the only thing it rests on

What the absence cost is the same near-miss against what the default branch
holds today, where all eleven packages run green, so nothing separated an entry
resting on a debt from one that does not.

Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
@iderex
iderex merged commit a5c4fba into main Aug 21, 2026
25 checks passed
@iderex
iderex deleted the contexts/the-permanent-absence-guard-left-the-default-branch branch August 21, 2026 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant